package com.hua.giftool.main.activity

import android.content.ContentValues
import android.content.Context
import android.media.MediaMetadataRetriever
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.MediaStore
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.add
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
import androidx.compose.material3.Checkbox
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import coil.ImageLoader
import coil.compose.rememberAsyncImagePainter
import coil.decode.GifDecoder
import coil.request.ImageRequest
import com.arthenica.ffmpegkit.FFmpegKit
import com.arthenica.ffmpegkit.FFmpegKitConfig
import com.arthenica.ffmpegkit.ReturnCode
import com.hua.giftool.R
import com.hua.giftool.base.BaseActivity
import com.hua.giftool.ui.theme.GifToolTheme
import com.hua.giftool.utils.checkOrRequestPermission
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import kotlin.math.log10
import kotlin.math.min
import kotlin.math.pow
import coil.size.Size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll


class MainActivity : BaseActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            GifToolTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    VideoToGifScreen()
                }
            }
        }
        checkPermission()
    }
    private fun checkPermission() {
        when {
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> checkOrRequestPermission(
                mutableListOf(
                    android.Manifest.permission.READ_MEDIA_IMAGES,
//                    android.Manifest.permission.READ_MEDIA_AUDIO,
                    android.Manifest.permission.READ_MEDIA_VIDEO
                ),
                {}
            )
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> checkOrRequestPermission(
                mutableListOf(
                    android.Manifest.permission.READ_EXTERNAL_STORAGE,
                    android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    android.Manifest.permission.MANAGE_EXTERNAL_STORAGE
                ),
                {}
            )
            else -> checkOrRequestPermission(
                mutableListOf(
                    android.Manifest.permission.READ_EXTERNAL_STORAGE,
                    android.Manifest.permission.WRITE_EXTERNAL_STORAGE
                ),
                {}
            )
        }
    }
}

object GifConstants {
    const val DEFAULT_FPS = 24
    const val DEFAULT_WIDTH = 512
    const val DEFAULT_HEIGHT = -1
    const val DEFAULT_OUTPUT_DIR = "FFmpegOutput"
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun <T : AppCompatActivity> T.VideoToGifScreen() {
    val context = LocalContext.current
    var selectedVideoUri by remember { mutableStateOf<Uri?>(null) }
    var conversionStatus by remember { mutableStateOf("") }
    val coroutineScope = rememberCoroutineScope()

    var targetFps by remember { mutableStateOf("${GifConstants.DEFAULT_FPS}") }
    var targetWidth by remember { mutableStateOf("${GifConstants.DEFAULT_WIDTH}") }
    var targetHeight by remember { mutableStateOf("${GifConstants.DEFAULT_HEIGHT}") }
    var estimatedFileSize by remember { mutableStateOf("") }
    var originalVideoDurationMs by remember { mutableStateOf<Long>(0) }

    var useCustomCommand by remember { mutableStateOf(false) }
    var customFFmpegCommand by remember { mutableStateOf("") }

    var isConverting by remember { mutableStateOf(false) }
    var conversionProgress by remember { mutableStateOf(0f) }

    val pickVideoLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.GetContent()
    ) { uri: Uri? ->
        selectedVideoUri = uri
        conversionStatus = if (uri != null) context.getString(R.string.conversion_status_selected, uri.lastPathSegment) else context.getString(R.string.conversion_status_no_selection)
        estimatedFileSize = ""
        if (uri != null) {
            originalVideoDurationMs = getDurationFromUri(context, uri)
            estimatedFileSize = estimateGifFileSize(
                context,
                uri,
                targetFps.toIntOrNull() ?: GifConstants.DEFAULT_FPS,
                targetWidth.toIntOrNull() ?: GifConstants.DEFAULT_WIDTH,
                targetHeight.toIntOrNull() ?: GifConstants.DEFAULT_HEIGHT,
                originalVideoDurationMs
            )
        }
        val inputVideoPathPlaceholder = "\"input_video_path\""
        val tempOutputGifPathPlaceholder = "\"output_gif_path\""
        customFFmpegCommand = "-i $inputVideoPathPlaceholder -vf \"fps=${targetFps.toIntOrNull() ?: GifConstants.DEFAULT_FPS},scale=${targetWidth.toIntOrNull() ?: GifConstants.DEFAULT_WIDTH}:${targetHeight.toIntOrNull() ?: GifConstants.DEFAULT_HEIGHT}:flags=lanczos,split[s0][s1];[s0]palettegen=stats_mode=full[p];[s1][p]paletteuse=dither=sierra2_4a\" -loop 0 -y $tempOutputGifPathPlaceholder"
    }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp)
            .verticalScroll(rememberScrollState()), // Add vertical scroll
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        Button(onClick = {
            pickVideoLauncher.launch("video/*")
        }, enabled = !isConverting) {
            Text(stringResource(R.string.select_video_button))
        }

        // Input fields for FPS, Width, Height
        OutlinedTextField(
            value = targetFps,
            onValueChange = { newValue ->
                targetFps = newValue
                val inputVideoPathPlaceholder = "\"input_video_path\""
                val tempOutputGifPathPlaceholder = "\"output_gif_path\""
                customFFmpegCommand = "-i $inputVideoPathPlaceholder -vf \"fps=${newValue.toIntOrNull() ?: GifConstants.DEFAULT_FPS},scale=${targetWidth.toIntOrNull() ?: GifConstants.DEFAULT_WIDTH}:${targetHeight.toIntOrNull() ?: GifConstants.DEFAULT_HEIGHT}:flags=lanczos,split[s0][s1];[s0]palettegen=stats_mode=full[p];[s1][p]paletteuse=dither=sierra2_4a\" -loop 0 -y $tempOutputGifPathPlaceholder"
                estimatedFileSize = estimateGifFileSize(
                    context,
                    selectedVideoUri,
                    newValue.toIntOrNull() ?: GifConstants.DEFAULT_FPS,
                    targetWidth.toIntOrNull() ?: GifConstants.DEFAULT_WIDTH,
                    targetHeight.toIntOrNull() ?: GifConstants.DEFAULT_HEIGHT,
                    originalVideoDurationMs
                )
            },
            label = { Text(stringResource(R.string.target_fps_label)) },
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
            modifier = Modifier.fillMaxWidth(),
            enabled = !useCustomCommand && !isConverting
        )

        OutlinedTextField(
            value = targetWidth,
            onValueChange = { newValue ->
                targetWidth = newValue
                val inputVideoPathPlaceholder = "\"input_video_path\""
                val tempOutputGifPathPlaceholder = "\"output_gif_path\""
                customFFmpegCommand = "-i $inputVideoPathPlaceholder -vf \"fps=${targetFps.toIntOrNull() ?: GifConstants.DEFAULT_FPS},scale=${newValue.toIntOrNull() ?: GifConstants.DEFAULT_WIDTH}:${targetHeight.toIntOrNull() ?: GifConstants.DEFAULT_HEIGHT}:flags=lanczos,split[s0][s1];[s0]palettegen=stats_mode=full[p];[s1][p]paletteuse=dither=sierra2_4a\" -loop 0 -y $tempOutputGifPathPlaceholder"
                estimatedFileSize = estimateGifFileSize(
                    context,
                    selectedVideoUri,
                    targetFps.toIntOrNull() ?: GifConstants.DEFAULT_FPS,
                    newValue.toIntOrNull() ?: GifConstants.DEFAULT_WIDTH,
                    targetHeight.toIntOrNull() ?: GifConstants.DEFAULT_HEIGHT,
                    originalVideoDurationMs
                )
            },
            label = { Text(stringResource(R.string.target_width_label)) },
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
            modifier = Modifier.fillMaxWidth(),
            enabled = !useCustomCommand && !isConverting
        )

        OutlinedTextField(
            value = targetHeight,
            onValueChange = { newValue ->
                targetHeight = newValue
                val inputVideoPathPlaceholder = "\"input_video_path\""
                val tempOutputGifPathPlaceholder = "\"output_gif_path\""
                customFFmpegCommand = "-i $inputVideoPathPlaceholder -vf \"fps=${targetFps.toIntOrNull() ?: GifConstants.DEFAULT_FPS},scale=${targetWidth.toIntOrNull() ?: GifConstants.DEFAULT_WIDTH}:${newValue.toIntOrNull() ?: GifConstants.DEFAULT_HEIGHT}:flags=lanczos,split[s0][s1];[s0]palettegen=stats_mode=full[p];[s1][p]paletteuse=dither=sierra2_4a\" -loop 0 -y $tempOutputGifPathPlaceholder"
                estimatedFileSize = estimateGifFileSize(
                    context,
                    selectedVideoUri,
                    targetFps.toIntOrNull() ?: GifConstants.DEFAULT_FPS,
                    targetWidth.toIntOrNull() ?: GifConstants.DEFAULT_WIDTH,
                    newValue.toIntOrNull() ?: GifConstants.DEFAULT_HEIGHT,
                    originalVideoDurationMs
                )
            },
            label = { Text(stringResource(R.string.target_height_label)) },
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
            modifier = Modifier.fillMaxWidth(),
            enabled = !useCustomCommand && !isConverting
        )

        // Custom FFmpeg Command Row
        Row(
            modifier = Modifier.fillMaxWidth(),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            Checkbox(
                checked = useCustomCommand,
                onCheckedChange = { checked -> useCustomCommand = checked },
                enabled = !isConverting
            )
            Text(stringResource(R.string.use_custom_command_checkbox))
        }

        // Conditionally display the custom command input field
        if (useCustomCommand) {
            OutlinedTextField(
                value = customFFmpegCommand,
                onValueChange = { customFFmpegCommand = it },
                label = { Text(stringResource(R.string.custom_ffmpeg_command_label)) },
                modifier = Modifier.fillMaxWidth(),
                enabled = !isConverting
            )
        }

        // Display estimated file size
        if (estimatedFileSize.isNotEmpty() && !useCustomCommand && !isConverting) {
            Text(text = stringResource(R.string.estimated_file_size_prefix, estimatedFileSize))
        }

        // Display animation and progress bar during conversion
        if (isConverting) {
            val imageLoader = ImageLoader.Builder(context)
                .components {
                    // Add the GifDecoder factory
                    // Note: Coil might automatically detect and use this if the dependency is present,
                    // but explicitly adding it ensures it's considered.
                    add(GifDecoder.Factory())
                }
                .build()
            Image(
                painter = rememberAsyncImagePainter(
                    model = ImageRequest.Builder(context)
                        .data(R.drawable.daomao)
                        .size(Size.ORIGINAL)
                        .build(),
                    imageLoader = imageLoader
                ),
                contentDescription = stringResource(R.string.conversion_status_converting),
                modifier = Modifier
                    .size(200.dp)
                    .align(Alignment.CenterHorizontally)
            )

            LinearProgressIndicator(
                progress = conversionProgress,
                modifier = Modifier.fillMaxWidth()
            )

            Text(text = "${(conversionProgress * 100).toInt()}%", modifier = Modifier.align(Alignment.CenterHorizontally))
        }

        selectedVideoUri?.let { uri ->
            Button(onClick = {
                isConverting = true
                conversionStatus = context.getString(R.string.conversion_status_converting)
                coroutineScope.launch {
                    val success = convertVideoToGif(
                        context,
                        uri,
                        targetFps.toIntOrNull() ?: GifConstants.DEFAULT_FPS,
                        targetWidth.toIntOrNull() ?: GifConstants.DEFAULT_WIDTH,
                        targetHeight.toIntOrNull() ?: GifConstants.DEFAULT_HEIGHT,
                        originalVideoDurationMs,
                        useCustomCommand,
                        customFFmpegCommand,
                        onProgress = { progress ->
                            conversionProgress = progress
                        }
                    )
                    isConverting = false
                    conversionProgress = 0f
                    conversionStatus =
                        if (success)
                            context.getString(R.string.conversion_successful, GifConstants.DEFAULT_OUTPUT_DIR)
                        else context.getString(R.string.conversion_failed)
                }
            }, enabled = selectedVideoUri != null && !isConverting) {
                Text(stringResource(R.string.convert_button))
            }
            // Display conversion status below the convert button
            Text(text = conversionStatus)
        }
    }
}

// Function to get actual file path from Uri (can be complex, simplified here)
// This is a common challenge with SAF Uris, and the implementation depends on the Uri type.
// For simplicity and demonstration, we'll try a common approach, but it might not work for all Uris.
fun getPathFromUri(context: Context, uri: Uri): String? {
    var path: String? = null
    val projection = arrayOf(MediaStore.Images.Media.DATA)
    val cursor = context.contentResolver.query(uri, projection, null, null, null)
    cursor?.use {
        if (it.moveToFirst()) {
            val columnIndex = it.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
            path = it.getString(columnIndex)
        }
    }
    return path
}

fun getDurationFromUri(context: Context, uri: Uri): Long {
    val retriever = MediaMetadataRetriever()
    try {
        retriever.setDataSource(context, uri)
        val duration = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
        return duration?.toLongOrNull() ?: 0
    } catch (e: Exception) {
        e.printStackTrace()
        return 0
    } finally {
        retriever.release()
    }
}

fun estimateGifFileSize(
    context: Context,
    videoUri: Uri?,
    targetFps: Int,
    targetWidth: Int,
    targetHeight: Int,
    originalDurationMs: Long
): String {
    if (videoUri == null || originalDurationMs <= 0 || targetFps <= 0 || targetWidth <= 0 && targetHeight <= 0) {
        return "" // 信息不完整，无法预估
    }

    // 粗略估算：假设每帧数据量与像素数量成正比，并考虑一些压缩因子
    // 这是一个非常简化的模型，实际情况复杂得多
    val estimatedFrames = (originalDurationMs / 1000.0 * targetFps).toInt()
    val estimatedPixelsPerFrame = if (targetWidth > 0 && targetHeight > 0) {
        targetWidth * targetHeight
    } else if (targetWidth > 0) {
        // 假设保持比例，需要获取原始视频宽高
        val originalSize = getVideoDimensionsFromUri(context, videoUri)
        if (originalSize.first > 0 && originalSize.second > 0) {
            (targetWidth * (originalSize.second.toFloat() / originalSize.first)).toInt() * targetWidth
        } else {
            targetWidth * GifConstants.DEFAULT_WIDTH // 无法获取原始比例，使用一个默认高度进行估算
        }
    } else if (targetHeight > 0) {
        // 假设保持比例，需要获取原始视频宽高
        val originalSize = getVideoDimensionsFromUri(context, videoUri)
        if (originalSize.first > 0 && originalSize.second > 0) {
            (targetHeight * (originalSize.first.toFloat() / originalSize.second)).toInt() * targetHeight
        } else {
            targetHeight * GifConstants.DEFAULT_WIDTH // 无法获取原始比例，使用一个默认宽度进行估算
        }
    } else {
        GifConstants.DEFAULT_WIDTH * GifConstants.DEFAULT_WIDTH // 使用一个默认分辨率进行估算
    }

    // 估算每像素的字节数 (GIF 通常使用 256 色调色板，每个像素可能需要 1 字节或更多用于颜色索引和控制信息)
    // 这里的 0.1 是一个非常粗略的经验系数，需要根据实际测试调整
    val bytesPerPixel = 0.68

    val estimatedTotalBytes = estimatedFrames * estimatedPixelsPerFrame * bytesPerPixel

    // 将字节转换为更易读的格式 (KB, MB)
    return formatBytes(estimatedTotalBytes.toLong())
}

// 获取视频分辨率函数 (用于预估)
fun getVideoDimensionsFromUri(context: Context, uri: Uri): Pair<Int, Int> {
    val retriever = MediaMetadataRetriever()
    try {
        retriever.setDataSource(context, uri)
        val width =
            retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toIntOrNull() ?: 0
        val height =
            retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toIntOrNull() ?: 0
        return Pair(width, height)
    } catch (e: Exception) {
        e.printStackTrace()
        return Pair(0, 0)
    } finally {
        retriever.release()
    }
}

// 格式化字节大小函数
fun formatBytes(bytes: Long): String {
    if (bytes <= 0) return "0 B"
    val units = arrayOf("B", "KB", "MB", "GB", "TB")
    val digitGroups = (log10(bytes.toDouble()) / log10(1024.0)).toInt()
    return String.format("%.2f %s", bytes / 1024.0.pow(digitGroups.toDouble()), units[digitGroups])
}

suspend fun convertVideoToGif(
    context: Context,
    inputUri: Uri,
    targetFps: Int,
    targetWidth: Int,
    targetHeight: Int,
    originalVideoDurationMs: Long,
    useCustomCommand: Boolean,
    customFFmpegCommandText: String,
    onProgress: (Float) -> Unit // Add progress callback
): Boolean {
    return withContext(Dispatchers.IO) {
        val inputVideoPath = getPathFromUri(context, inputUri)
        if (inputVideoPath == null) {
            println("Error: Could not get file path from Uri")
            onProgress(0f) // Reset progress on error
            return@withContext false
        }
        val inputFile = File(inputVideoPath)
        if (!inputFile.exists()) {
            println("Error: Input file does not exist")
            onProgress(0f) // Reset progress on error
            return@withContext false
        }

        val tempOutputGifFile = File(context.cacheDir, "${inputFile.nameWithoutExtension}_temp.gif")
        val tempOutputGifPath = tempOutputGifFile.absolutePath

        val ffmpegCommand = if (useCustomCommand) {
            customFFmpegCommandText
                .replace("\"input_video_path\"", "\"$inputVideoPath\"")
                .replace("\"output_gif_path\"", "\"$tempOutputGifPath\"")
        } else {
            "-i \"$inputVideoPath\"" +
                    " -vf \"fps=$targetFps,scale=${targetWidth}:${targetHeight}:flags=lanczos,split[s0][s1];[s0]palettegen=stats_mode=full[p];[s1][p]paletteuse=dither=sierra2_4a\"" +
                    " -loop 0" +
                    " -y" +
                    " \"$tempOutputGifPath\""
        }

        // Set up progress listener
        FFmpegKitConfig.enableLogCallback { log ->
            // You might need to parse FFmpeg logs to estimate progress
            // This is a simplified example and may require more sophisticated parsing
            val logMessage = log.message
            if (logMessage.contains("frame=")) {
                try {
                    val frameMatch = "frame=\\s*(\\d+)".toRegex().find(logMessage)
                    val currentFrame = frameMatch?.groupValues?.get(1)?.toInt() ?: 0

                    val durationMatch = "Duration: (\\d{2}):(\\d{2}):(\\d{2})\\.(\\d{2})".toRegex().find(logMessage)
                    val totalDurationMs = if (durationMatch != null) {
                        val hours = durationMatch.groupValues[1].toInt()
                        val minutes = durationMatch.groupValues[2].toInt()
                        val seconds = durationMatch.groupValues[3].toInt()
                        val milliseconds = durationMatch.groupValues[4].toInt() * 10 // FFmpeg duration has hundredths of a second
                        (hours * 3600 + minutes * 60 + seconds) * 1000L + milliseconds
                    } else {
                        originalVideoDurationMs // Use the duration obtained earlier if log parsing fails
                    }


                    val totalFramesEstimate = (totalDurationMs / 1000.0 * targetFps).toInt()

                    if (totalFramesEstimate > 0 && currentFrame > 0) {
                        val progress =
                            min(currentFrame.toFloat() / totalFramesEstimate, 1.0f) // Ensure progress doesn't exceed 1
                        onProgress(progress)
                    }

                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }

        val session = FFmpegKit.execute(ffmpegCommand)
        val returnCode = session.returnCode

        val success = ReturnCode.isSuccess(returnCode)

        // Disable log callback after execution
        FFmpegKitConfig.enableLogCallback(null)


        if (success) {
            println("Video to GIF conversion successful to temp file: $tempOutputGifPath")
            val result = saveGifToPublicDirectory(context, tempOutputGifFile, GifConstants.DEFAULT_OUTPUT_DIR)
            tempOutputGifFile.delete()
            onProgress(1.0f) // Set progress to 100% on success
            return@withContext result
        } else {
            println("Video to GIF conversion failed. Return code: $returnCode")
            println("Error message: ${session.failStackTrace}")
            tempOutputGifFile.delete()
            onProgress(0f) // Reset progress on failure
            return@withContext false
        }
    }
}

// 新增函数：将临时 GIF 文件保存到公共目录
suspend fun saveGifToPublicDirectory(context: Context, tempFile: File, subDirectory: String): Boolean {
    return withContext(Dispatchers.IO) {
        val resolver = context.contentResolver
        val collection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
        } else {
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI
        }

        val fileName = tempFile.name
        val mimeType = "image/gif"

        val contentValues = ContentValues().apply {
            put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
            put(MediaStore.Images.Media.MIME_TYPE, mimeType)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                // 对于 Android Q 及以上，使用 RELATIVE_PATH
                put(
                    MediaStore.Images.Media.RELATIVE_PATH,
                    Environment.DIRECTORY_PICTURES + File.separator + subDirectory
                )
                put(MediaStore.Images.Media.IS_PENDING, 1) // 标记为待处理，稍后设置为 0
            } else {
                // 对于旧版本，需要构造绝对路径
                val picturesDir =
                    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
                val appDir = File(picturesDir, subDirectory)
                if (!appDir.exists()) {
                    appDir.mkdirs() // 创建子目录
                }
                val outputFile = File(appDir, fileName)
                put(MediaStore.Images.Media.DATA, outputFile.absolutePath)
            }
        }

        try {
            val uri = resolver.insert(collection, contentValues)

            if (uri == null) {
                println("Error creating MediaStore entry")
                return@withContext false // 如果 uri 为 null，直接返回 false
            }

            // 如果 uri 不为 null，继续处理
            resolver.openOutputStream(uri).use { outputStream ->
                if (outputStream != null) {
                    tempFile.inputStream().copyTo(outputStream)
                    println("Copied GIF to MediaStore Uri: $uri")
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                        contentValues.clear()
                        contentValues.put(MediaStore.Images.Media.IS_PENDING, 0)
                        resolver.update(uri, contentValues, null, null)
                    }
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                        MediaScannerConnection.scanFile(
                            context,
                            arrayOf(tempFile.absolutePath),
                            arrayOf(mimeType)
                        ) { path, uri ->
                            println("MediaScanner scanned $path: -> uri=$uri")
                        }
                    }
                    return@withContext true // 成功写入并更新状态后返回 true
                } else {
                    println("Error opening output stream for Uri: $uri")
                    resolver.delete(uri, null, null) // 清理 MediaStore 记录
                    return@withContext false // 无法获取输出流返回 false
                }
            }

        } catch (e: Exception) {
            println("Error saving GIF to public directory: ${e.message}")
            return@withContext false // 捕获异常返回 false
        }
    }
}